import UIKit

var str = "Hello, playground"

func greet(person:String)->String{
    let greeting = "hello, " + person + "!"
    return greeting;
}

print(greet(person: "小明"))
print(greet(person: "小李"))

//多重返回值函数
//你可以用元组（tuple）类型让多个值作为一个复合值从函数中返回。

func minMax(array:[Int]) -> (min:Int,max:Int){
    var currentMin = array[0];
    var currentMax = array[0];
    
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value;
        }else if value > currentMax{
            currentMax = value;
        }
    }
    return (currentMin,currentMax);
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print(bounds)
print("\(bounds.min) , \(bounds.max)")

//隐式返回的函数
//如果一个函数的整个函数体是一个单行表达式，这个函数可以隐式地返回这个表达式。
func greeting1(for person:String)->String{
    "Hello, " + person + "!"
}
print(greeting1(for: "小王"))

//函数参数标签和参数名称
//每个函数参数都有一个参数标签（argument label）以及一个参数名称（parameter name）。参数标签在调用函数的时候使用；调用的时候需要将函数的参数标签写在对应的参数前面。参数名称在函数的实现中使用。默认情况下，函数参数使用参数名称来作为它们的参数标签。

func greet2(person:String,from homeTown:String) -> String{
    "hello \(person)! glad you could visit from \(homeTown)"
}
print(greet2(person: "Bill", from: "Cupertino"))

//忽略参数标签
//如果你不希望为某个参数添加一个标签，可以使用一个下划线（_）来代替一个明确的参数标签。
func greet3(_ person:String,from homeTown:String) -> String{
    "hello \(person)! glad you could visit from \(homeTown)"
}
//print(greet3(person: "Bill", from: "Cupertino"))
print(greet3("张三", from: "张家屯"))

//默认参数值
//你可以在函数体中通过给参数赋值来为任意一个参数定义默认值（Deafult Value）。当默认值被定义后，调用这个函数时可以忽略这个参数。
func add(sum1:Int=1,sum2:Int=2)->Int{
    sum1 + sum2;
}
print(add())

//输入输出参数
//函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。如果你想要一个函数可以修改参数的值，并且想要在这些修改在函数调用结束后仍然存在，那么就应该把这个参数定义为输入输出参数（In-Out Parameters）。
//定义一个输入输出参数时，在参数定义前加 inout 关键字。
//你只能传递变量给输入输出参数。你不能传入常量或者字面量，因为这些量是不能被修改的。当传入的参数作为输入输出参数时，需要在参数名前加 & 符，表示这个值可以被函数修改。
//输入输出参数不能有默认值，而且可变参数不能用 inout 标记。
func swapTwoInts(_ a: inout Int,_ b: inout Int){
    let tempa = a;
    a = b;
    b = tempa;
}

var inta = 3;
var intb = 100;
swap(&inta, &intb)
print("inta = \(inta),intb = \(intb)")

//函数类型
//每个函数都有种特定的函数类型，函数的类型由函数的参数类型和返回类型组成。

func add1(a:Int,b:Int)->Int{
    a+b;
}

func multiply(a:Int,b:Int)->Int{
    a*b;
}

//这两个函数的类型是 (Int, Int) -> Int，可以解读为:“这个函数类型有两个 Int 型的参数并返回一个 Int 型的值”。

func pringHelloWorld(){
    print("hello world")
}
//这个函数的类型是：() -> Void，或者叫“没有参数，并返回 Void 类型的函数”。

//使用函数类型
//在 Swift 中，使用函数类型就像使用其他类型一样。例如，你可以定义一个类型为函数的常量或变量，并将适当的函数赋值给它：
var mathFunction:(Int,Int) -> Int = add1(a:b:);
//现在，你可以用 mathFunction 来调用被赋值的函数了：
print("Result:\(mathFunction(2,3))")

//函数类型作为参数类型
//你可以用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提供。
func printMathResult(_ mathfunction1:(Int,Int) -> Int,a:Int,b:Int){
    print("result:\(mathfunction1(a,b))")
}
printMathResult(mathFunction, a: 2, b: 1)

